package com.lazyframework.commons.util;

import com.lazyframework.commons.constant.DateFormatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * @author maoning
 * date 2019/4/25 15:10
 */
public class DateUtils {

    public static final String DEFAULT_DATE_PATTERN = DateFormatter.PATTERN_01;       // "yyyy-MM-dd";
    public static final String DEFAULT_DATETIME_PATTERN = DateFormatter.PATTERN_10;   // "yyyy-MM-dd HH:mm:ss";

    public static String format() {
        return format(DEFAULT_DATETIME_PATTERN);
    }

    public static String format(String pattern) {
        return format(LocalDateTime.now(), pattern);
    }

    public static String format(LocalDateTime time, String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String currentWeek() {
        return ChnWeekParse.parse(Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
    }

    public static DateOfWeek getDateOfWeek() {
        return DateOfWeek.newInstance();
    }

    public static Date parseUTC(String utcTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        return sdf.parse(utcTime);
    }

    /**
     * 获取当前时间是今年的第几周
     * @return
     */
    public static int getWeeks() {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    public static class DateOfWeek {

        private final LocalDate start;

        private final LocalDate end;

        DateOfWeek() {
            Calendar now = Calendar.getInstance();
            // 得出今天是本周第几天
            int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
            // 本周第一天
            now.add(Calendar.DAY_OF_WEEK, -dayOfWeek + 1);
            this.start = LocalDate.of(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, now.get(Calendar.DATE));
            // 本周最后一天
            now.add(Calendar.DAY_OF_WEEK, 6);
            this.end = LocalDate.of(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, now.get(Calendar.DATE));
        }

        public static DateOfWeek newInstance() {
            return new DateOfWeek();
        }

        public String getStart() {
            return start.toString();
        }

        public String getEnd() {
            return end.toString();
        }

        @Override
        public String toString() {
            return "DateOfWeek{" +
                    "start=" + start +
                    ", end=" + end +
                    '}';
        }
    }

    /**
     * 返回星期一的日期
     * @return
     */
    public static Calendar dateOfMonday() {
        Calendar cl = Calendar.getInstance();
        int dayOfWeek = cl.get(Calendar.DAY_OF_WEEK)-1;
        cl.add(Calendar.DATE, -dayOfWeek+1);
        LocalDate dateOfMonday = LocalDate.of(
                cl.get(Calendar.YEAR), cl.get(Calendar.MONTH)+1, cl.get(Calendar.DATE)
        );
        Instant instant = dateOfMonday.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        cl.setTime(Date.from(instant));
        return cl;
    }

    public static Calendar getThisWeekMonday() {
        return getWeekMonday(LocalDate.now().getYear(), getWeeks());
    }

    /**
     * 获取下周一的日期
     * @return
     */
    public static Calendar getNextWeekMonday() {
        return getWeekMonday(LocalDate.now().getYear(), getWeeks()+1);
    }

    /**
     * 返回指定年份指定周星期一的日期
     * @param years
     * @param weeks
     * @return
     */
    public static Calendar getWeekMonday(int years, int weeks) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, years);

        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }

        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);

        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);

        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);

        // 用传入的周数减去当前周数，得出传入时间和当前时间相差的周数
        cal.add(Calendar.WEEK_OF_YEAR, weeks - cal.get(Calendar.WEEK_OF_YEAR));

        return cal;
    }

    public static class ChnWeekParse {

        public static final String[] WEEKS_0 = { "一", "二", "三", "四", "五", "六", "日" };

        public static String parse(int week) {
            return WEEKS_0[(week - 1) - 1];
        }

    }

    public static int getAgeByBirth(Date birthDay) {
        int age;
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) { //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException(
                    "The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) age--;//当前日期在生日之前，年龄减一
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }

}
